package com.itheima.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

@Aspect //aop切面类
//@Component
@Slf4j
public class RecordTimeAspect {

    //@PointCut切入点表达式, 抽取公共的表达式
    @Pointcut("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
    public void pc(){}

    // 第1个* 任意返回值类型
    // 第2个* 任意方法
    // 第3个.. 任意参数
    // Around: 环绕通知, 方法声明时返回类型必须是object
    //@Around("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
    public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable {
        // 开始时间
        //@Before
        long start = System.currentTimeMillis();
        // 执行原始目标方法
        try {
            Object result = joinPoint.proceed();
            //结束的时间
            //@AfterReturning
            long end = System.currentTimeMillis();
            log.info("方法执行耗时：{}", end - start);
            return new Object();
        } catch (Throwable e) {
            //@AfterThrowing
            throw new RuntimeException(e);
        } finally {
            //@After
        }
    }

    /**
     * 前置通知
     */
    //@Before("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
    @Before("pc()")
    public void before(){
        //方法的参数，可以加上JoinPoint参数，也可以不加
        log.info("方法执行开始");
    }

    /**
     * 返回通知
     */
    @AfterReturning("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
    public void afterReturning(JoinPoint joinPoint){
        //joinPoint切入点
        log.info("方法执行结束");
    }

    /**
     * 异常通知
     */
    @AfterThrowing("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
    public void afterThrowing(JoinPoint joinPoint){
        //joinPoint切入点
        log.info("方法执行异常");
    }

    /**
     * 最终通知,后置通知
     */
    @After("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
    public void after(JoinPoint joinPoint){
        //joinPoint切入点
        log.info("方法执行结束,不管是否发生异常都会执行");
    }

}
